/** @type {import("webpack").Configuration} */
const ESLintPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
// npm i -D @pmmmwh/react-refresh-webpack-plugin react-refresh
const ReactFefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const path = require("path");
const FileListPlugin = require("../plugins/cusPlugins");

// 环境变量
const isProd = process.env.NODE_ENV === "production";

// 处理样式loader函数
function getStyleLoaders(pre) {
  return [
    isProd ? MiniCssExtractPlugin.loader : "style-loader",
    "css-loader",
    {
      // 解决css兼容
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: ["postcss-preset-env"],
        },
      },
    },
    pre,
  ].filter(Boolean);
}

module.exports = {
  entry: "./src/main.js",
  output: {
    path: isProd ? path.resolve(__dirname, "../dist") : undefined,
    filename: isProd
      ? "static/js/[name].[contenthash:10].js"
      : "static/js/[name].js",
    chunkFilename: isProd
      ? "static/js/[name].[contenthash:10].chunk.js"
      : "js/[name].chunk.js",
    assetModuleFilename: "static/media/[hash:10][ext][query]",
    clean: true,
  },
  resolveLoader: {
    modules: ["node_modules", "./loaders"],
  },
  module: {
    rules: [
      // css
      {
        test: /\.css$/,
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      // 图片
      {
        test: /\.(png|jpe?g|gif|webp|svg)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            // 小于10kb的图片会转成base64 减少http请求,体积会变大一点
            maxSize: 10 * 1024, // 10kb
          },
        },
      },
      // 其他资源
      {
        test: /\.(woff|woff2|eot|ttf|otf|mp3|mp4|avi)$/,
        type: "asset/resource",
      },
      // js
      {
        test: /\.jsx?$/,
        include: path.resolve(__dirname, "../src"),
        use: [
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true, // 开启babel缓存
              cacheCompression: false, // 关闭缓存文件压缩， 压缩回影响打包速度
              plugins: [!isProd && "react-refresh/babel"].filter(Boolean), // 激活JS的HMR
            },
          },
          // 自定义loader  配合resolveLoader
          // {
          //   loader: "self-loader",
          //   options: {
          //     name: "hello-self-loadder",
          //   },
          // },
        ],
      },
      // 自定义loader  配合resolveLoader
      {
        test: /\.md$/,
        use: ["html-loader", "markdown-loader"],
      },
    ],
  },
  plugins: [
    new ESLintPlugin({
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules",
      cache: true,
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    isProd &&
      new MiniCssExtractPlugin({
        filename: "css/[name].[contenthash:10].css",
        chunkFilename: "css/[name].chunk.[contenthash:10].css",
      }),
    isProd &&
      new CopyWebpackPlugin({
        patterns: [
          {
            from: path.resolve(__dirname, "../public"),
            to: path.resolve(__dirname, "../dist"),
            globOptions: {
              // 忽略文件
              ignore: ["**/index.html"],
            },
          },
        ],
      }),
    !isProd && new ReactFefreshWebpackPlugin(),
    new FileListPlugin(),
  ].filter(Boolean),
  mode: isProd ? "production" : "development",
  devtool: isProd ? "source-map" : "cheap-module-source-map",
  optimization: {
    splitChunks: {
      chunks: "all",
      cacheGroups: {
        // react react-dom react-router-dom 一起打包
        // antd 单独打包
        // 剩余nodemodules单独打包
        react: {
          test: /[\\/]node_modules[\\/]react(.*)?[\\/]/,
          name: "react-chunk",
          priority: 40,
        },
        antd: {
          test: /[\\/]node_modules[\\/]antd[\\/]/,
          name: "antd-chunk",
          priority: 30,
        },
        libs: {
          test: /[\\/]node_modules[\\/]/,
          name: "libs-chunk",
          priority: 20,
        },
      },
    },
    // 代码分割会导致缓存失效，配置runtimeChunk
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}.js`,
    },
    minimize: isProd, // 开启代码压缩
    minimizer: [
      new CssMinimizerPlugin(), // 开启css压缩
      new TerserWebpackPlugin(), // 开启js压缩
    ],
  },
  // webpack解析模块加载选项
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "../src"),
    },
    // 自动补全文件扩展名
    extensions: [".js", ".json", ".jsx"],
  },
  devServer: {
    host: "localhost",
    port: 3000,
    open: true,
    hot: true,
    historyApiFallback: true, // 解决404问题
  },
};
